using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Ltf.Remoting.Operations;
using Ltf.Remoting.TeamFoundation;
using Ltf.Remoting.TFAccess;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.IO;
using Ltf.Remoting.Commands;

namespace Ltf.MonitorLizard.Helpers
{
	// helper functions for context menus
	class ContextMenus
	{
		public struct DiffPair
		{
			public string Left;
			public string Right;
			public bool IsFolder;
			public TFServerConnection Connection;

			public DiffPair(string left, string right, bool isFolder, TFServerConnection connection)
			{
				Left = left;
				Right = right;
				IsFolder = isFolder;
				Connection = connection;
			}
		}

		public static void LoadDiffMenu(ContextMenuStrip cms, string path, string textPrefix, TFServerConnection connection, Workspace workspace)
		{
			LoadDiffMenu(cms, path, string.Empty, textPrefix,connection, workspace);
		}

		public static void LoadDiffMenu(ContextMenuStrip cms, string path, string tempCopyPath, string textPrefix,TFServerConnection connection, Workspace workspace)
		{
			string compareFile = (tempCopyPath == string.Empty) ? path : tempCopyPath;

			Stack<ToolStripItem> diffItems = new Stack<ToolStripItem>();
			foreach (ToolStripItem cm in cms.Items)
				if (cm.Name.StartsWith("cmDiff"))
					diffItems.Push(cm);

			while (diffItems.Count > 0)
				cms.Items.Remove(diffItems.Pop());

			string name = string.Empty;
			int version = 0;
			int deletionId=0;
			bool isFolder = false;

			if (path.StartsWith("$"))
			{
				string fname;
				LizardFileAccess.GetNameAndVersionFromPath(path, out fname, out version, out deletionId);
				VersionSpec versionSpec = VersionSpec.Latest;
				if (version > 0)
					versionSpec = new ChangesetVersionSpec(version);
				Item item = connection.VersionControlServer.GetItem(fname,versionSpec,deletionId);
				isFolder = (item.ItemType == ItemType.Folder);
			}
			else
				isFolder = Directory.Exists(path);

	//		LizardFileAccess.GetNameAndVersionFromPath(path,out name,out version);

			int localVersion, serverVersion;
			string localPath, ServerPath;

			if (workspace != null)
			{
				WorkspaceOperators wso = new WorkspaceOperators(connection, workspace);
				wso.GetVersionInfo(path, out localPath, out ServerPath, out localVersion, out serverVersion);
			}
			else
			{
				ServerOperators so = new ServerOperators(connection.VersionControlServer);
				so.GetVersionInfo(name, out localPath, out ServerPath, out localVersion, out serverVersion);
			}

			if (path.StartsWith("$") && !string.IsNullOrEmpty(localPath))
			{
				// path supplied is a repo path, so allow compare with working copy
				ToolStripItem cm = cms.Items.Add(textPrefix + "Working copy", null, GetDiffClickHandler(workspace));
				cm.Tag = new DiffPair(compareFile, localPath, isFolder, connection);
				cm.Name = "cmDiffWorkingCopy";
			}
			if (version != -1 && version != localVersion)
			{
				// path supplied is a repo path, so allow compare with working copy
				ToolStripItem cm = cms.Items.Add(textPrefix + "Working base", null, GetDiffClickHandler(workspace));
				string path2 = LizardFileAccess.SetPathVersionAndDeletionId(ServerPath, localVersion, deletionId);
				cm.Tag = new DiffPair(compareFile, path2, isFolder, connection);
				cm.Name = "cmDiffWorkingBase";
			}
	//		if (!(version == 0 && !path.StartsWith("$")) && version != serverVersion)
			if ( version != serverVersion)
				{
				// path supplied is a repo path, so allow compare with working copy
				ToolStripItem cm = cms.Items.Add(textPrefix + "Server latest", null, GetDiffClickHandler(workspace));
				string path2 = string.Format("{0};c{1};d{2}", ServerPath, serverVersion, deletionId);
				cm.Tag = new DiffPair(compareFile, path2, isFolder, connection);
				cm.Name = "cmDiffServerLatest";
			}
			if (path.StartsWith("$"))
			{
				VersionSpec versionSpec = VersionSpec.Latest;
				if (version > 0)
					versionSpec = new ChangesetVersionSpec(version);
				Item item = workspace.VersionControlServer.GetItem(ServerPath, versionSpec, deletionId);
				TFHistory history = new TFHistory(connection, path, workspace);
				int previous = history.GetPreviousRevisionId(new ChangesetVersionSpec(item.ChangesetId));
				if (previous != item.ChangesetId)
				{
					string path2 = LizardFileAccess.SetPathVersion(ServerPath, previous);
					if (LizardFileAccess.RepoPathExists(path2))
					{
						// path supplied is a repo path, so allow compare with previous version
						ToolStripItem cm = cms.Items.Add(textPrefix + "Previous version", null, GetDiffClickHandler(workspace));
						cm.Tag = new DiffPair(compareFile, path2, isFolder, connection);
						cm.Name = "cmDiffServerPrevious";
					}
				}
			}

		}


		private static EventHandler GetDiffClickHandler(Workspace workspace)
		{
			DiffMenuClickHandlerWrapper wrapper = new DiffMenuClickHandlerWrapper(workspace);
			EventHandler handler = new EventHandler(wrapper.DiffMenuClick);
			return handler;
		}

		private class DiffMenuClickHandlerWrapper
		{
			private Workspace workspace;
			public DiffMenuClickHandlerWrapper(Workspace workspace)
			{
				this.workspace = workspace;
			}

			public void DiffMenuClick(object sender, EventArgs args)
			{
				if (sender is ToolStripItem && (sender as ToolStripItem).Tag is DiffPair)
				{
					DiffPair dp = (DiffPair)(sender as ToolStripItem).Tag;
					if (dp.IsFolder)
					{
						Ltf.MonitorLizard.Forms.DirDiff dd = new Ltf.MonitorLizard.Forms.DirDiff(dp.Left, dp.Right, dp.Connection, dp.Connection);
						dd.Show();
						dd.Compare();
					}
					else
					{
						string ext=Path.GetExtension(dp.Left);
						if (ext == ".dll" || ext == ".exe" || ext.StartsWith(".dll;") || ext.StartsWith(".exe;"))
						{
							Ltf.MonitorLizard.Forms.ExecutableDiff ed = new Ltf.MonitorLizard.Forms.ExecutableDiff(dp.Left, dp.Right);
							ed.Show();
						}
						else
						{
							Ltf.MonitorLizard.Forms.TwoWayDiff twd = new Ltf.MonitorLizard.Forms.TwoWayDiff(dp.Left, dp.Right, workspace, workspace);
							twd.CompareSideBySide(dp.Left, dp.Right);
							twd.Show();
						}
					}
				}
			}
		}
	}
}
